package com.example.filter;

import com.example.utils.RequestUserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.UUID;

/**
 * 请求日志过滤器，记录所有请求的URL和相关信息
 */
@Slf4j
@Component
@Order(1)
public class RequestLoggingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 生成请求唯一标识
        String requestId = UUID.randomUUID().toString();
        httpRequest.setAttribute("requestId", requestId);

        // 获取请求信息
        String requestURI = httpRequest.getRequestURI();
        String method = httpRequest.getMethod();
        String ip = getClientIP(httpRequest);

        // 记录请求开始日志
        log.info("请求开始 - [{}] {} {} IP: {}", requestId, method, requestURI, ip);

        // 记录请求参数 (可选)
        if (!"GET".equals(method)) {
            String params = getRequestParams(httpRequest);
            log.debug("请求参数 - [{}] {}", requestId, params);
        }

        long startTime = System.currentTimeMillis();
        try {
            // 执行请求
            chain.doFilter(request, response);

            // 获取用户信息(可能在拦截器中被设置)
            Long userId = null;
            String username = null;
            try {
                userId = RequestUserHolder.getUserId();
                username = RequestUserHolder.getUsername();
            } catch (Exception e) {
                // 获取用户信息失败，继续处理
            }

            // 请求处理完成，记录成功信息
            long duration = System.currentTimeMillis() - startTime;
            if (userId != null) {
                log.info("请求完成 - [{}] {} {} 耗时: {}ms 用户: {}({})",
                        requestId, method, requestURI, duration, username, userId);
            } else {
                log.info("请求完成 - [{}] {} {} 耗时: {}ms",
                        requestId, method, requestURI, duration);
            }

        } catch (Exception e) {
            // 获取用户信息(可能在拦截器中被设置)
            Long userId = null;
            String username = null;
            try {
                userId = RequestUserHolder.getUserId();
                username = RequestUserHolder.getUsername();
            } catch (Exception ex) {
                // 获取用户信息失败，继续处理
            }

            // 记录异常信息
            long duration = System.currentTimeMillis() - startTime;
            if (userId != null) {
                log.error("请求异常 - [{}] {} {} 耗时: {}ms 用户: {}({}) 错误: {} 堆栈: {}",
                        requestId, method, requestURI, duration, username, userId,
                        e.getMessage(), getStackTrace(e));
            } else {
                log.error("请求异常 - [{}] {} {} 耗时: {}ms 错误: {} 堆栈: {}",
                        requestId, method, requestURI, duration, e.getMessage(), getStackTrace(e));
            }

            throw e;
        }
    }

    /**
     * 获取客户端IP
     */
    private String getClientIP(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 对于通过多个代理的情况，第一个IP为客户端真实IP，多个IP按照','分割
        if (ip != null && ip.length() > 15 && ip.indexOf(",") > 0) {
            ip = ip.substring(0, ip.indexOf(","));
        }
        return ip;
    }

    /**
     * 获取请求参数
     */
    private String getRequestParams(HttpServletRequest request) {
        // 简单实现，实际应用中可能需要更复杂的处理，比如处理表单或JSON请求体
        StringBuilder params = new StringBuilder();
        request.getParameterMap().forEach((key, values) -> {
            params.append(key).append("=");
            if (values != null && values.length > 0) {
                params.append(values[0]);
            }
            params.append(", ");
        });

        if (params.length() > 0) {
            params.delete(params.length() - 2, params.length());
        }

        return params.toString();
    }

    /**
     * 获取异常堆栈信息
     */
    private String getStackTrace(Exception e) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        pw.close();
        return sw.toString();
    }
}